Go to PersonalMicroCosms.com
Send feedback to the author (EricTerrell@hotmail.com)
Go to the C# Programmable Calculator Website
RPN calculators require numbers to be entered before the operation is performed. Operations have no priority - they are performed in the order entered. Consequently RPN calculators do not need parentheses.
Since numbers must be entered before the operation to be performed, to evaluate 1 + 2:
press the 1 button
press the Enter button
press the 2 button
press the + button
The result, 3, is left on the stack.
| Expression | How to Evaluate |
|---|---|
| 17 * (3 + 4) | 17 Enter 3 Enter 4 + * |
| 3.14 * 123.4^2 | 3.14 Enter 123.4 X^2 * |
| (3^2 * (7^2 - 8)) / 5 | 7 X^2 8 - 3 Enter X^2 * 5 / |
| Button | Accelerator | What it does |
|---|---|---|
| Drop | Alt+r | Removes the topmost stack item. |
| Swap | Alt+S | Exchanges the topmost two stack items. |
| Clear Ent. | Alt+l | Clears the number entry area. |
| Ch. Sign | Alt+h | Changes the sign of the topmost stack item (i.e. multiplies it by -1). Use this button to enter negative numbers. |
| Recip | Alt+p | Replaces the topmost stack item with its reciprocal (i.e. divides 1 by it). |
| Sqrt | Alt+q | Replaces the topmost stack item with its square root. |
| Clear All | Alt+A | Removes all stack items and clears the number entry area. |
| Enter | Alt+E or Enter key | Moves the number from the number entry area to the top of the stack or duplicates the item on the top of the stack. |
| X ^ 2 | Alt+X | Replaces the topmost stack item with its square (i.e. multiplies the topmost stack item by itself). |
| Y ^ X | Alt+Y | Raises the next-to-topmost stack item to the power of the topmost stack item. |
| % | Alt+% | Converts a number into a percentage. For example, converts 5 to 0.05. |
| n! | Alt+! | Computes the factorial of n (e.g. n!). |
| Pi | Alt+i | Returns Pi (3.14159265358979). |
| / | / | Divides the second-to-topmost stack item by the topmost stack item. |
| * | * | Multiplies the second-to-topmost stack item by the topmost stack item. |
| - | - | Subtracts the topmost stack item from the second-to-topmost stack item. |
| + | + | Adds the second-to-topmost stack item to the topmost stack item. |
| 0-9 | 0-9 | Appends the digit to the right of the number entry area. |
| . | . | Appends the decimal point to the right of the number entry area. |
| <-- | Backspace | Removes the rightmost character from the number entry area. |
| Tab | Button | What it does |
|---|---|---|
| Main | Floating Point | Displays numbers in the stack with an arbitrary number of digits to the right of the decimal point. |
| Fixed Point | Displays numbers in the stack with the specified number of digits to the right of the decimal point and thousands separators. | Sci Not | Converts the specified number and power of ten to a number in scientific notation. |
| Integer Part | Computes the whole number portion of a floating-point number. | |
| Fractional Part | Computes the fractional portion of a floating-point number. | |
| Round | Rounds the specified number to the closest whole number. | |
| Floor | Computes the largest whole number less than or equal to the specified number. | |
| Ceiling | Computes the smallest whole number greater than or equal to the specified number. | |
| Math | |x| | Converts the number to a positive number if it's negative. |
| Fib | Computes the specified Fibonacci number. | |
| LN | Computes the natural logarithm of the specified number. | |
| e^X | Computes the inverse natural logarithm of the specified number. | |
| e | Computes Euler's constant. | |
| Log | Computes the decimal logarithm of the specified number. | |
| 10^X | Computes the inverse decimal logarithm of the specified number. | |
| Find Fraction | Computes a fraction that approximates a rational number. | |
| Random | Computes a pseudorandom number between 0 and 1. | |
| Statistics | ||
| Mean (Average) | Returns the average of all numbers on the stack | |
| Median | Returns the median of all numbers on the stack. | |
| Variance | Returns the variance of all numbers on the stack. | |
| Standard Deviation | Returns the standard deviation of all numbers on the stack. | Trig | Sin | Computes the sine of the angle (which must be in radians). |
| Cos | Computes the cosine of the angle (which must be in radians). | |
| Tan | Computes the tangent of the angle (which must be in radians). | |
| ASin | Computes the arcsine. | |
| ACos | Computes the arccosine. | |
| ATan | Computes the arctangent. | |
| Cosh | Computes the hyperbolic cosine. | |
| Sinh | Computes the hyperbolic sine. | |
| Tanh | Computes the hyperbolic tangent. | |
| ACosh | Computes the inverse hyperbolic cosine. | |
| ASinh | Computes the inverse hyperbolic sine. | |
| ATanh | Computes the inverse hyperbolic tangent. | |
| Angles | Radians | Converts an angle expressed in degrees into the equivalent angle in radians. |
| Degrees | Converts an angle expressed in radians into the equivalent angle in degrees. | |
| DMS2Decimal | Converts an angle expressed in degrees, minutes, and seconds into the equivalent angle in decimal format. For example, converts 23 degrees, 59 minutes, 13 seconds to 23.9869444444444. | |
| Angle Between Locations | Returns the angle subtended at the center of the earth by the two positions expressed as latitude and longitude. See DistanceBetweenLocations, below | |
| Distance Between Locations | Computes the great circle distance between two cities, given their latitudes and longitudes. | |
| Computer Math | Enter Binary | Prompts the user to enter a binary (base 2) number. |
| Enter Octal | Prompts the user to enter an octal (base 8) number. | |
| Enter Decimal | Prompts the user to enter a decimal (base 10) number. | |
| Enter Hexadecimal | Prompts the user to enter an hexadecimal (base 16) number. | |
| To Binary | Converts a number to binary (base 2) format. | |
| To Octal | Converts a number to octal (base 8) format. | |
| To Decimal | Converts a number to decimal (base 10) format. | |
| To Hexadecimal | Converts a number to hexadecimal (base 16) format. | |
| AND | Computes the bitwise and of two numbers | |
| OR | Computes the bitwise inclusive or of two numbers | |
| XOR | Computes the bitwise exclusive or of two numbers | |
| 1's complement | Converts all of a number's 1-bits to 0 and vice versa. | |
| 2's complement | Converts all of a number's 1-bits to 0 and vice versa and then adds 1 to the result. | |
| Shift Left << | Shifts a number's bits to the left (in other words, multiplies it by 2). | |
| Shift Right >> | Shifts a numbers' bits to the right (in other words, divides it by 2). | |
| Memory | Store | Stores the value in the specified register. |
| Recall | Retrieves the value in the specified register. | |
| Finance | Amortize | Computes a loan payment schedule. Note: the amortization schedule is only valid in the USA. |
| Dates & Times | Now | Returns the current date and time (in local timezone). |
| Today | Returns the current date (in the local timezone). Time is midnight. | |
| To Universal Time | Converts the specified date and time to Tniversal Time (GMT). | |
| To Local Time | Converts the specified date and time from Universal Time to the local time zone. | |
| Get Date |
If the user selects a date, a DateTime object will be placed
on the stack.
If the user cancels the dialog box, a null value will be placed on the stack. |
|
| Get Date Range |
If the user selects a date range, a SelectionRange object will
be placed on the stack. To extract the start and end date
from the SelectionRange object, use SelectionRange.Begin
and SelectionRange.End. If the user cancels the dialog box, a null value will be placed on the stack. |
|
| Add Days | Adds the specified number of days to a date. | |
| Subtract Days | Subtracts the specified number of days from a date. | |
| Subtract Dates | Subtracts the dates and returns the resulting TimeSpan. |
Note: Any pre-programmed function can be replaced with your own function or deleted.
To program an existing programmable button, right-click the programmable button. An integrated source code editor will be launched, allowing you to modify that button's function.
To program a new button, press the Edit Functions button and enter one or more functions. When you press the OK button the new functions will be automatically assigned to programmable buttons.
A programmable function's button is only enabled when the stack contains the correct number of arguments that the function expects, in the correct datatypes. In other words, if a function's button requires two double-precision floating-point numbers, there must be at least two items on the stack, and the top two must be of type double.
To supply a function with arguments,
add items to the stack in the order that they appear in the function declaration. For example,
consider the following function:
public static double SciNot(double n, double PowerOf10)
// Allow the user to enter numbers in scientific notation.
// Return n * 10 ^ PowerOf10.
{
return n * Math.Pow(10.0, PowerOf10);
}
Enter the number first, then enter the power of 10. For example, enter
6.0221367 * 1023 as follows:
6.0221367 Enter 23 Enter SciNot
The integrated source code editor has a multiple-line indent and unindent feature. To indent multiple lines, select the lines and press the Tab key. To unindent multiple lines, select the lines and press Shift+Tab.
If a function is taking too long, press Esc to cancel it. Note: you may need to single-click the icon in the taskbar before pressing Esc:
[assembly:Tab("Main", 1)]
[assembly:Tab("Math", 2)]
[assembly:Tab("Trig", 3)]
[assembly:Tab("Angles", 4)]
[assembly:Tab("Memory", 5)]
[assembly:Tab("Finance", 6)]
[assembly:Tab("Dates & Times", 7)]
In the Tab attribute, the first argument specifies the name of the tab. The second argument specifies the order in which it appears, from left to right.
// Display numerical values as floating point.
[Button("Main")]
public static void FloatingPoint()
{
iapi.DisplayFormat = "";
}
The first argument to the Button attribute specifies the name of the tab to which the programmable button belongs. The second argument specifies the button text. This argument is optional and only needs to be specified if the button text differs from the method's name. For example:
[Button("Math", "n!")]
public static long Factorial(int n)
In this case the second argument is specified since the button text, "n!", is different than the method's name ("Factorial").
By default, when a custom function returns a null value, that null will be placed on the stack. To prevent this from happening, add the [DiscardNull] attribute above the function.
For example:
[Button("Computer Math", "Enter Binary")]
[DiscardNull()]
public static Integer EnterBinaryNumber()
...
Objects are displayed in the stack by calling their ToString() method. Your functions can return objects of any class, or values of any primitive type (int, bool, float, double, byte, etc).
If an item's value is wider than the stack, it will be truncated with an ellipsis (...) on its far right. To see the entire value, either double-click it, or selected it and select the View / Selected Stack Value menu item.
C# Programmable Calculator automatically saves the stack contents every time you close the program, and restores the stack when you run it later. One exception: If objects of user-defined classes are stored on the stack, the stack will not be restored when the program is run again.
int index; Object o; ... globals[index] = o;The Store and Recall programmable functions use the global variable array to store and recall values.
By default, your custom functions can only the System namespace and a few others. To access other namespaces, first add the appropriate "using" statement, e.g.:
using System.Windows.Forms;
At this point, if the corresponding assembly has not been added, you'll get an error message like the following:
To add the assembly, press Configure Assemblies in the Error dialog box, or select Options / Settings in the main window:
When possible, values on the stack are converted to be compatible with function arguments. If the stack contains a floating-point value and the corresponding function argument is an integral type, the floating-point value is truncated and converted into that integral type.
C# code ignores numerical overflow by default. If you want your code to throw an exception when an overflow happens, use one of the following techniques:
Select Options / Settings. Select the Misc. tab and check the Check for numeric overflow checkbox. This setting affects all of your functions.
To enable overflow checking for specific functions, use checked blocks as follows:
public static long Factorial(int n)
// Calculates n! using a recursive algorithm.
{
long result = 1;
// By default, C# code will not throw
// exceptions when overflows happen. To
// ensure that an exception is thrown when
// overflows occur, enclose the code in a
// checked block.
checked
{
if (n > 1)
{
result = n * Factorial(n - 1);
}
}
return result;
}
Checked expressions can also be enclosed in parenthesis, for example:
public static void Overflow()
{
short x = 32000;
short y = 32000;
short z = checked((short) (x + y));
}
You can create and use user-defined classes like the following:
public class UserDefined
{
public UserDefined(int intValue)
{
this.intValue = intValue;
}
public override String ToString()
{
return intValue.ToString();
}
public int intValue;
}
public UserDefined pushUserDefined()
{
return new UserDefined(42);
}
public int popUserDefined(UserDefined userDefined)
{
return userDefined.intValue;
}
If you call a function that places a user-defined object on the stack, and then make changes to functions (by pressing the Edit Functions button, or by adding or deleting any assemblies), any user-defined objects on the stack cannot be passed to functions.
In this situation you'll get the following error message:
One or more of the stack values did not match the corresponding
argument types expected by method.
To resolve this issue, simply press the Clear All button. This will remove the incompatible objects from the stack. When user-defined objects are subsequently pushed on the stack they can be passed to functions.
In other words, you can't store user-defined objects on the stack, and then make changes to their class(es), and then expect the old, out-of-date, objects to be compatible with methods that are expecting the new objects.
Finally, if there are user-defined objects on the stack when the program is closed, when it is run again the stack will be empty.
C# Programmable Calculator includes an assembly named CSPCUtil.dll that provides some useful utility functions that you can use in your programmable functions:
PromptForPrice launches a dialog box with an initial value of 1.00 displayed. When the user presses the OK button a double value is returned containing the specified value. If the user presses Cancel, null is returned.
public double PromptForPrice()
{
return (double) Util.Prompt("Enter Price", "Price:", "1.00", typeof(double));
}
FibonacciReport generates a textual report displaying the Fibonacci numbers from 1 to max. It uses an ArrayList to store the lines that will be used in the report because ArrayLists can dynamically grow. It's easy to convert an ArrayList in to a String array, just use the ArrayList.ToArray method.
[Button("Test")]
public void FibonacciReport(int max)
{
TextLines textLines = new TextLines();
for (int i = 1; i <= max; i++)
{
textLines.AddLine("Fib({0}) = {1}", i, Fib(i));
}
textLines.Display("Fibonacci Numbers");
}
BrowserDemo first launches the dialog box displaying the www.PersonalMicroCosms.com website. After the user presses the Close button, the dialog box is launched again, displaying the specified HTML.
public static void BrowserDemo()
{
// Display the www.PersonalMicroCosms.com website:
Util.DisplayBrowser("Personal MicroCosms", "www.PersonalMicroCosms.com", false);
// Display HTML text:
String htmlText = "<HTML><BODY><P>THIS IS A PARAGRAPH</P></BODY></HTML>";
Util.DisplayBrowser("HTML", htmlText, true);
}
graphicsDemo creates a GraphicsForm, launches it, and then draws random lines with random colors.
public void graphicsDemo()
{
const int width = 2000;
const int height = 2000;
using (GraphicsForm gf = new GraphicsForm("interesting graphic", new Size(width, height)))
{
Graphics g = gf.GraphicsObject;
Random r = new Random();
for (int i = 0; i < 1000; i++)
{
int x1 = r.Next(width);
int x2 = r.Next(width);
int y1 = r.Next(height);
int y2 = r.Next(height);
g.DrawLine(new Pen(Color.FromArgb(r.Next(256), r.Next(256), r.Next(256))), x1, y1, x2, y2);
}
gf.ShowDialog();
}
}
C# Programmable Calculator has an API that can be called from your programmable functions. To access this API, use the iapi member and call the following methods:
| Method/Property | Description | Arguments | Return Value |
|---|---|---|---|
| DisplayFormat Property |
The DisplayFormat property specifies how numerical values will be displayed.
Assign this property to an empty string for default formatting. Assign to "F{digits}" for fixed-point display, where {digits} is the number of digits to the right of the decimal point. For example, use "F2" to display currency amounts. Use "N{digits}" for fixed-point display with thousands separators, for example, use "N2" to display currency amounts. |
n/a | the display format String |
| FullDisplayFormat Property | The FullDisplayFormat readonly property returns the display format specified by the DisplayFormat property, but in a format that can be used by String.Format(), for example "{0:F2}". NOTE: This display format string is used to format numerical values in the stack. |
n/a | the full display format String. |
Use the istack member variable to manipulate the stack in custom functions. the istack object implements the IStack interface:
| Method/Property | Description | Arguments | Return Value |
|---|---|---|---|
| StackSize Property | Returns the number of items on the stack | n/a | Number of items on the stack (int) |
| PopItem | Returns the item on the top of the stack | n/a | Item on the top of the stack (object) |
| PushItem | Inserts the specified item on the top of the stack | Item to push (object) | n/a (this is a void method) |
| ReadItem | Returns the item on the top of the stack without removing it from the stack | n/a | Item on the top of the stack (object) |
For example, the expression istack.StackSize will be equal to the number of items on the stack.
If you create classes that implement this interface, objects of that class on the stack will be automatically converted to doubles when necessary. For example, if an object that implements IConvertToDouble is on the stack when the user presses the Recip button, the object will be converted to a double. Then the reciprocal will be calculated and the result will be placed on the stack.
The IConvertToDouble interface is in the CSPCUtil assembly.
| Method/Property | Description | Arguments | Return Value |
|---|---|---|---|
| ToDouble | converts the object to a double | n/a | Value of the object (double) |
In your functions you can use Debug.Assert to ensure that specified conditions are true. If they are ever not true, a message box will be displayed, which will help you find the error in your code.
For example, since dividing by zero is an error, the following function uses Assert to verify that the denominator is never zero. If it ever is, an error message will be displayed that pinpoints the precise location of the problem in your code.
public double divide(double numerator, double denominator)
{
// denominator must not be zero!
Debug.Assert(denominator != 0.0);
return numerator / denominator;
}
To enable Asserts in your code, make sure you've included the following using statement:
using System.Diagnostics;
Then select Options / Settings and select the Misc. tab and make sure the Allow debugging features checkbox is checked.
You can add code to your functions that will output trace messages for debugging purposes. For example:
public void TRACEDemo(double d)
{
Trace.WriteLine("User entered a value of " + d.ToString());
}
The trace messages will appear in a separate window.
To enable Asserts in your code, make sure you've included the following using statement:
using System.Diagnostics;
Then select Options / Settings and select the Misc. tab and make sure the Allow tracing features checkbox is checked. Then select View / Trace Window, which will launch the dialog box in which the trace messages will appear.
| Version | Notes |
|---|---|
| 1.18 |
Updated the source code to be compatible with .Net 2.0. You can create a .Net 2.0 version by importing the project and building the program. If you compile a .Net 2.0 version of this program and run it, you will need to update your LIB environment (see the error message text and remove the folder path that it complains about). Bug fixes: (GUI elements were being accessed by threads that did not create them). .Net 2.0 automatically detects this type of bug. A consequence of these bug fixes is that the IAPI interface no longer includes a TheMainForm property, and utility methods that previously took a Form argument no longer do. Another consequence of these bug fixes is that modal dialogs launched by custom functions are no longer children of the main form (if the were that would require accessing the main form from a thread that did not create it which is a no-no. |
| 1.17 |
Reduced the Edit Functions form's load time. I used NProf to find the performance hotspot (too many regular expression calls). I highly recommend NProf! Put spaces in pre-programmed function names. For example, the button that previously had the label "FloatingPoint" now has the label "Floating Point". |
| 1.16 |
Added the ability to programmatically manipulate the stack in custom functions. See Programmatically Manipulating the Stack for further details. Added a Statistics Tab. |
| 1.15 |
The main form is now resizable. If you increase the size the stack will take up the extra space. The number entry area and the stack are now right-aligned and have the Courier New font. The [DiscardNull] attribute can now be used to automatically discard nulls returned by a function. By default, nulls returned by a function are placed on the stack. Added a Computer Math tab containing functions to convert numbers between various bases, perform bitwise logical operations, and shifts. Moved %, n! and Pi functions from the Main tab to the area below the stack. Added an IConvertToDouble interface. If you create classes that implement this interface, objects of that class on the stack will be automatically converted to doubles when necessary. For example, if an object that implements IConvertToDouble is on the stack when the user presses the Recip button, the object will be converted to a double. Then the reciprocal will be calculated and the result will be placed on the stack. When you are using the code editor and you select Edit / Add Function, the active tab is selected in the drop-down combo box by default. Bug Fix: In previous versions, if the Remember Window Sizes and Positions option was selected, if the program was closed while minimized, when it was subsequently launched it would never become un-minimized. Bug Fix: In previous versions text in the stack was sometimes clipped. For example, the bottom of the y in Infinity was sometimes clipped. You can force Infinity to display in the stack by dividing a number by zero. |
| 1.14 |
In previous versions the leftmost tab became active after editing programmable functions. Now the originally active tab remains active after editing, unless that tab was removed during the editing process. Added GetWebPageText method to the CSPCUtil Utility Library. Made updates based on FxCop's advice. Bug Fix: After pressing the Ent. Hex button you can only enter an 8 hexadecimal digit number to prevent numeric overflow. Bug Fix: The +, -, *, / buttons were inappropriately disabled for items on the stack of the following types: UInt16, UInt32, UInt64. |
| 1.13 |
Simplified and improved the creation of textual reports. See CSPCUtilUtilityLibrary for further details. Users can now customize the font used in textual reports. After calling CSPCUtil.TextLines.Display, click on the Font! menu item to choose a font. Added table of contents to on-line help. Added a Rembember Window Sizes and Positions checkbox to the Appearance tab of the Options / Settings dialog box. If this checkbox is checked, most dialog boxes will launch at their previous positions, unless the screen resolution has changed. |
| 1.12 |
The setup program is now MSI based. User configuration settings and source code are now stored in the user's application data folder. This will allow users with different user accounts to use this program and have their own configuration settings and custom functions. In the code for custom functions (Funcs.cs), specified the full namespace (CSPCUtil.Util) because the Utils class was clashing with classes in other namespaces with the same name. For example, the System.Runtime.Serialization.Formatters.Soap namespace has a Util class. |